package com.zenithmind.document.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.zenithmind.common.context.UserContext;
import com.zenithmind.common.result.Result;
import com.zenithmind.document.pojo.dto.DocumentTagCreateDTO;
import com.zenithmind.document.pojo.dto.DocumentTagUpdateDTO;
import com.zenithmind.document.pojo.query.DocumentTagQueryDTO;
import com.zenithmind.document.pojo.vo.DocumentTagVO;
import com.zenithmind.document.service.DocumentTagService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import java.util.List;

/**
 * 文档标签控制器
 * 遵循单一职责原则：专注于文档标签相关的HTTP接口
 * 遵循依赖倒置原则：依赖抽象服务接口
 * 
 * @author ZenithMind Team
 * @since 2025-01-09
 */
@Slf4j
@RestController
@RequestMapping("/api/document/tag")
@RequiredArgsConstructor
@Validated
@Tag(name = "文档标签管理", description = "文档标签相关接口")
public class DocumentTagController {

    private final DocumentTagService documentTagService;

    @PostMapping
    @Operation(summary = "创建标签", description = "创建新的文档标签")
    public Result<DocumentTagVO> createTag(@Valid @RequestBody DocumentTagCreateDTO createDTO) {
        log.info("创建标签请求: name={}", createDTO.getName());
        
        DocumentTagVO result = documentTagService.createTag(createDTO);
        
        return Result.success(result);
    }

    @PutMapping("/{id}")
    @Operation(summary = "更新标签", description = "更新文档标签信息")
    public Result<Boolean> updateTag(
            @Parameter(description = "标签ID", required = true) @PathVariable @NotBlank String id,
            @Valid @RequestBody DocumentTagUpdateDTO updateDTO) {
        
        log.info("更新标签请求: id={}", id);
        
        Boolean result = documentTagService.updateTag(id, updateDTO);
        
        return Result.success(result);
    }

    @DeleteMapping("/{id}")
    @Operation(summary = "删除标签", description = "删除文档标签")
    public Result<Boolean> deleteTag(
            @Parameter(description = "标签ID", required = true) @PathVariable @NotBlank String id) {
        
        log.info("删除标签请求: id={}", id);
        
        Boolean result = documentTagService.deleteTag(id);
        
        return Result.success(result);
    }

    @DeleteMapping("/batch")
    @Operation(summary = "批量删除标签", description = "批量删除文档标签")
    public Result<Boolean> batchDeleteTags(
            @Parameter(description = "标签ID列表", required = true) @RequestBody @NotEmpty List<String> ids) {
        
        log.info("批量删除标签请求: ids={}", ids);
        
        Boolean result = documentTagService.batchDeleteTags(ids);
        
        return Result.success(result);
    }

    @GetMapping("/page")
    @Operation(summary = "分页查询标签", description = "分页查询文档标签列表")
    public Result<IPage<DocumentTagVO>> getTagPage(@Valid DocumentTagQueryDTO queryDTO) {
        log.info("分页查询标签请求");
        
        IPage<DocumentTagVO> result = documentTagService.getTagPage(queryDTO);
        
        return Result.success(result);
    }

    @GetMapping("/{id}")
    @Operation(summary = "获取标签详情", description = "获取文档标签详细信息")
    public Result<DocumentTagVO> getTagDetail(
            @Parameter(description = "标签ID", required = true) @PathVariable @NotBlank String id) {
        
        log.info("获取标签详情请求: id={}", id);
        
        DocumentTagVO result = documentTagService.getTagDetail(id);
        
        return Result.success(result);
    }

    @GetMapping("/name/{name}")
    @Operation(summary = "根据名称获取标签", description = "根据标签名称获取标签信息")
    public Result<DocumentTagVO> getTagByName(
            @Parameter(description = "标签名称", required = true) @PathVariable @NotBlank String name) {
        
        log.info("根据名称获取标签请求: name={}", name);
        
        DocumentTagVO result = documentTagService.getTagByName(name);
        
        return Result.success(result);
    }

    @GetMapping("/all")
    @Operation(summary = "获取所有标签", description = "获取所有文档标签")
    public Result<List<DocumentTagVO>> getAllTags() {
        log.info("获取所有标签请求");
        
        List<DocumentTagVO> result = documentTagService.getAllTags();
        
        return Result.success(result);
    }

    @GetMapping("/search")
    @Operation(summary = "搜索标签", description = "根据关键词搜索标签")
    public Result<List<DocumentTagVO>> searchTags(
            @Parameter(description = "搜索关键词", required = true) @RequestParam @NotBlank String keyword,
            @Parameter(description = "限制数量") @RequestParam(required = false, defaultValue = "20") Integer limit) {
        
        log.info("搜索标签请求: keyword={}", keyword);
        
        List<DocumentTagVO> result = documentTagService.searchTags(keyword, limit);
        
        return Result.success(result);
    }

    @GetMapping("/hot")
    @Operation(summary = "获取热门标签", description = "获取热门标签列表")
    public Result<List<DocumentTagVO>> getHotTags(
            @Parameter(description = "限制数量") @RequestParam(required = false, defaultValue = "10") Integer limit) {
        
        log.info("获取热门标签请求: limit={}", limit);
        
        List<DocumentTagVO> result = documentTagService.getHotTags(limit);
        
        return Result.success(result);
    }

    @GetMapping("/latest")
    @Operation(summary = "获取最新标签", description = "获取最新创建的标签列表")
    public Result<List<DocumentTagVO>> getLatestTags(
            @Parameter(description = "限制数量") @RequestParam(required = false, defaultValue = "10") Integer limit) {
        
        log.info("获取最新标签请求: limit={}", limit);
        
        List<DocumentTagVO> result = documentTagService.getLatestTags(limit);
        
        return Result.success(result);
    }

    @GetMapping("/user")
    @Operation(summary = "获取用户标签", description = "获取当前用户创建的标签")
    public Result<List<DocumentTagVO>> getUserTags(
            @Parameter(description = "限制数量") @RequestParam(required = false, defaultValue = "20") Integer limit) {
        
        log.info("获取用户标签请求");
        
        String userId = UserContext.getUserId();
        List<DocumentTagVO> result = documentTagService.getUserTags(userId, limit);
        
        return Result.success(result);
    }

    @GetMapping("/document/{documentId}")
    @Operation(summary = "获取文档标签", description = "获取指定文档的标签列表")
    public Result<List<DocumentTagVO>> getDocumentTags(
            @Parameter(description = "文档ID", required = true) @PathVariable @NotBlank String documentId) {
        
        log.info("获取文档标签请求: documentId={}", documentId);
        
        List<DocumentTagVO> result = documentTagService.getDocumentTags(documentId);
        
        return Result.success(result);
    }

    @PostMapping("/document/{documentId}/add")
    @Operation(summary = "为文档添加标签", description = "为指定文档添加标签")
    public Result<Boolean> addTagsToDocument(
            @Parameter(description = "文档ID", required = true) @PathVariable @NotBlank String documentId,
            @Parameter(description = "标签名称列表", required = true) @RequestBody @NotEmpty List<String> tagNames) {
        
        log.info("为文档添加标签请求: documentId={}, tagNames={}", documentId, tagNames);
        
        String userId = UserContext.getUserId();
        Boolean result = documentTagService.addTagsToDocument(documentId, tagNames, userId);
        
        return Result.success(result);
    }

    @DeleteMapping("/document/{documentId}/remove")
    @Operation(summary = "从文档移除标签", description = "从指定文档移除标签")
    public Result<Boolean> removeTagsFromDocument(
            @Parameter(description = "文档ID", required = true) @PathVariable @NotBlank String documentId,
            @Parameter(description = "标签名称列表", required = true) @RequestBody @NotEmpty List<String> tagNames) {
        
        log.info("从文档移除标签请求: documentId={}, tagNames={}", documentId, tagNames);
        
        Boolean result = documentTagService.removeTagsFromDocument(documentId, tagNames);
        
        return Result.success(result);
    }

    @PutMapping("/document/{documentId}/replace")
    @Operation(summary = "替换文档标签", description = "替换指定文档的所有标签")
    public Result<Boolean> replaceDocumentTags(
            @Parameter(description = "文档ID", required = true) @PathVariable @NotBlank String documentId,
            @Parameter(description = "新标签名称列表", required = true) @RequestBody List<String> tagNames) {
        
        log.info("替换文档标签请求: documentId={}, tagNames={}", documentId, tagNames);
        
        String userId = UserContext.getUserId();
        Boolean result = documentTagService.replaceDocumentTags(documentId, tagNames, userId);
        
        return Result.success(result);
    }

    @PostMapping("/batch/add")
    @Operation(summary = "批量为文档添加标签", description = "批量为多个文档添加标签")
    public Result<Boolean> batchAddTagsToDocuments(
            @Parameter(description = "文档ID列表", required = true) @RequestBody @NotEmpty List<String> documentIds,
            @Parameter(description = "标签名称列表", required = true) @RequestParam @NotEmpty List<String> tagNames) {
        
        log.info("批量为文档添加标签请求: documentIds={}, tagNames={}", documentIds, tagNames);
        
        String userId = UserContext.getUserId();
        Boolean result = documentTagService.batchAddTagsToDocuments(documentIds, tagNames, userId);
        
        return Result.success(result);
    }

    @GetMapping("/cloud")
    @Operation(summary = "获取标签云数据", description = "获取标签云展示数据")
    public Result<List<Object>> getTagCloudData(
            @Parameter(description = "限制数量") @RequestParam(required = false, defaultValue = "50") Integer limit) {
        
        log.info("获取标签云数据请求: limit={}", limit);
        
        List<Object> result = documentTagService.getTagCloudData(limit);
        
        return Result.success(result);
    }

    @GetMapping("/{tagId}/related")
    @Operation(summary = "获取相关标签", description = "获取与指定标签相关的标签")
    public Result<List<DocumentTagVO>> getRelatedTags(
            @Parameter(description = "标签ID", required = true) @PathVariable @NotBlank String tagId,
            @Parameter(description = "限制数量") @RequestParam(required = false, defaultValue = "10") Integer limit) {
        
        log.info("获取相关标签请求: tagId={}, limit={}", tagId, limit);
        
        List<DocumentTagVO> result = documentTagService.getRelatedTags(tagId, limit);
        
        return Result.success(result);
    }

    @PostMapping("/merge")
    @Operation(summary = "合并标签", description = "将源标签合并到目标标签")
    public Result<Boolean> mergeTags(
            @Parameter(description = "源标签ID", required = true) @RequestParam @NotBlank String sourceTagId,
            @Parameter(description = "目标标签ID", required = true) @RequestParam @NotBlank String targetTagId) {
        
        log.info("合并标签请求: sourceTagId={}, targetTagId={}", sourceTagId, targetTagId);
        
        Boolean result = documentTagService.mergeTags(sourceTagId, targetTagId);
        
        return Result.success(result);
    }

    @PutMapping("/{tagId}/rename")
    @Operation(summary = "重命名标签", description = "重命名指定标签")
    public Result<Boolean> renameTag(
            @Parameter(description = "标签ID", required = true) @PathVariable @NotBlank String tagId,
            @Parameter(description = "新名称", required = true) @RequestParam @NotBlank String newName) {
        
        log.info("重命名标签请求: tagId={}, newName={}", tagId, newName);
        
        Boolean result = documentTagService.renameTag(tagId, newName);
        
        return Result.success(result);
    }

    @GetMapping("/check")
    @Operation(summary = "检查标签是否存在", description = "检查指定名称的标签是否存在")
    public Result<Boolean> checkTagExists(
            @Parameter(description = "标签名称", required = true) @RequestParam @NotBlank String name) {
        
        log.info("检查标签是否存在请求: name={}", name);
        
        Boolean result = documentTagService.checkTagExists(name);
        
        return Result.success(result);
    }

    @PostMapping("/create-or-get")
    @Operation(summary = "创建或获取标签", description = "创建新标签或获取已存在的标签")
    public Result<DocumentTagVO> createOrGetTag(
            @Parameter(description = "标签名称", required = true) @RequestParam @NotBlank String name) {
        
        log.info("创建或获取标签请求: name={}", name);
        
        String userId = UserContext.getUserId();
        DocumentTagVO result = documentTagService.createOrGetTag(name, userId);
        
        return Result.success(result);
    }

    @GetMapping("/suggestions")
    @Operation(summary = "获取标签建议", description = "根据输入获取标签建议")
    public Result<List<String>> getTagSuggestions(
            @Parameter(description = "输入文本", required = true) @RequestParam @NotBlank String input,
            @Parameter(description = "限制数量") @RequestParam(required = false, defaultValue = "10") Integer limit) {
        
        log.info("获取标签建议请求: input={}", input);
        
        List<String> result = documentTagService.getTagSuggestions(input, limit);
        
        return Result.success(result);
    }

    @PostMapping("/extract")
    @Operation(summary = "提取标签", description = "从文档内容中自动提取标签")
    public Result<List<String>> extractTagsFromContent(
            @Parameter(description = "文档内容", required = true) @RequestBody @NotBlank String content,
            @Parameter(description = "限制数量") @RequestParam(required = false, defaultValue = "10") Integer limit) {
        
        log.info("提取标签请求: limit={}", limit);
        
        List<String> result = documentTagService.extractTagsFromContent(content, limit);
        
        return Result.success(result);
    }

    @GetMapping("/trends")
    @Operation(summary = "获取标签趋势", description = "获取标签使用趋势数据")
    public Result<List<Object>> getTagTrends(
            @Parameter(description = "统计天数") @RequestParam(required = false, defaultValue = "30") Integer days,
            @Parameter(description = "限制数量") @RequestParam(required = false, defaultValue = "20") Integer limit) {
        
        log.info("获取标签趋势请求: days={}, limit={}", days, limit);
        
        List<Object> result = documentTagService.getTagTrends(days, limit);
        
        return Result.success(result);
    }

    @PostMapping("/cleanup")
    @Operation(summary = "清理未使用标签", description = "清理未被使用的标签")
    public Result<Integer> cleanupUnusedTags() {
        log.info("清理未使用标签请求");
        
        Integer result = documentTagService.cleanupUnusedTags();
        
        return Result.success(result);
    }

    @PostMapping("/sync")
    @Operation(summary = "同步标签统计", description = "同步标签使用统计数据")
    public Result<Boolean> syncTagStatistics() {
        log.info("同步标签统计请求");
        
        Boolean result = documentTagService.syncTagStatistics();
        
        return Result.success(result);
    }

    @GetMapping("/recommend")
    @Operation(summary = "推荐标签", description = "为当前用户推荐标签")
    public Result<List<DocumentTagVO>> recommendTagsToUser(
            @Parameter(description = "限制数量") @RequestParam(required = false, defaultValue = "10") Integer limit) {
        
        log.info("推荐标签请求: limit={}", limit);
        
        String userId = UserContext.getUserId();
        List<DocumentTagVO> result = documentTagService.recommendTagsToUser(userId, limit);
        
        return Result.success(result);
    }
}
